<?php

declare (strict_types=1);

namespace magein\think\pay;

use magein\pay\data\NoticeData;
use magein\pay\data\PayOrderData;
use magein\pay\extension\PayOrderInterface;
use magein\pay\PayException;
use magein\think\pay\model\PayOrderModel;
use magein\utils\Validator;

class PayOrder implements PayOrderInterface
{
    /**
     * 获取支付编号
     * @return string
     */
    public function getPayNo(): string
    {
        $random = rand(10000, 999999) . rand(10000, 99999);
        return date('YmdHis') . str_pad($random, 14, '0', STR_PAD_LEFT);
    }

    /**
     * @param PayOrderData $payData
     * @return bool
     * @throws PayException
     */
    public function create(PayOrderData $payData): bool
    {
        if ($payData->getTotalAmount() <= 0) {
            PayException::code(400211);
        }

        $notify_url = urldecode($payData->getNotifyUrl());
        $return_url = urldecode($payData->getReturnUrl());
        $return_url = $return_url ?: $notify_url;
        if ($notify_url && !Validator::url($notify_url)) {
            PayException::code(400215);
        }

        if ($return_url && !Validator::url($return_url)) {
            PayException::code(400217);
        }

        $model = new PayOrderModel();
        $model->channel_id = $payData->getChannelId();
        $model->user_id = $payData->getUserId();
        $model->pay_no = $payData->getPayNo();
        $model->order_no = $payData->getOrderNo();
        $model->platform_id = $payData->getPlatformId();
        $model->subject = $payData->getSubject();
        $model->trade_type = $payData->getTradeType();
        $model->appid = $payData->getAppId();
        $model->merchant_id = $payData->getMerchantId();
        $model->total_amount = $payData->getTotalAmount();
        $model->coupon_amount = $payData->getCouponAmount();
        $model->coupon_info = $payData->getCouponInfo();
        $model->scene = $payData->getScene();
        $model->notify_url = $notify_url;
        $model->return_url = $return_url;
        $model->remark = $payData->getRemark();

        return $model->save();
    }

    public function modify(NoticeData $notifyData)
    {
        $pay_no = $notifyData->getPayNo();

        if (empty($pay_no)) {
            return false;
        }

        $payOrder = PayOrderModel::_payNo($pay_no);
        if (empty($payOrder)) {
            return false;
        }

        if ($payOrder['trade_no']) {
            return false;
        }

        if ($payOrder['result'] == PayOrderModel::RESULT_SUCCESS) {
            return false;
        }

        $payOrder->trade_no = $notifyData->getTradeNo();
        $payOrder->reason = $notifyData->getReason();
        $payOrder->result = $notifyData->getResult();
        $payOrder->notify_date = $notifyData->getNotifyDate();
        $payOrder->notify_data = $notifyData->getNotifyData() ? json_encode($notifyData->getNotifyData()) : '';

        return $payOrder->save();
    }

    public function getByPayNo($pay_no): array
    {
        if (empty($pay_no)) {
            return [];
        }

        $record = PayOrderModel::_payNo($pay_no);

        return $record ? $record->toArray() : [];
    }
}